<template>
  <div class="app-container">
    <el-form size="small" :inline="true">
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery('userResult')">进行绑定关系的识别验证</el-button>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery('allResult')">与绑定关系无关的识别验证</el-button>



        <!-- <el-button type="primary" icon="el-icon-view" size="mini" @click="handleOilStain()">图片油污检测</el-button>
        <el-button type="warning" icon="el-icon-view" size="mini" @click="handleOilStainValueSetting()">油污阈值设置</el-button>
        <el-button type="primary" icon="el-icon-view" size="mini" @click="handleShelter()">图片遮挡检测</el-button>
        <el-button type="warning" icon="el-icon-setting" size="mini" @click="handleShelterValueSetting()">遮挡阈值设置</el-button> -->


        <el-button type="primary" icon="el-icon-search" size="mini" @click="irregularFigure()">风幕柜算法测试</el-button>
        <el-button type="primary" icon="el-icon-search" size="mini" @click=" handleV5">陈列算法v5测试</el-button>
        <!-- <el-button type="primary" icon="el-icon-search" size="mini" @click=" handleV5('健力宝')">陈列算法v5测试（健力宝）</el-button> -->
      </el-form-item>
      <el-row> 
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleErrorTest">图片异常检测</el-button>
        <el-button type="warning" icon="el-icon-setting" size="mini" @click="handleErrorThresholdSet">异常检测阈值设置</el-button>
      </el-row>
    </el-form>

    <el-dialog title="异常检测" :visible.sync="errorTestdialogOpen" :close-on-click-modal="false" @close="cancel"
      width="800px" append-to-body>
      <el-form ref="errorTestForm" :model="errorTestForm"  label-width="120px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="异常类型" prop="errorType">
              <el-select v-model="errorTestForm.errorType" clearable filterable placeholder="请选择">
                <el-option v-for="item in errorType_list" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <!-- <el-col :span="24">
            <el-form-item label="阈值" prop="threshold">
              <el-input v-model="errorTestForm.threshold" placeholder="请输入阈值" />
            </el-form-item>
          </el-col> -->
          <el-col :span="24">
            <el-form-item label="阈值" prop="threshold">
              <el-input v-model="errorTestForm.threshold" placeholder="请输入阈值" @input="inputValueChange" type="number"
                oninput="if(value > 100)value = 100;if(value<0)value = 0" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="图片url" prop="imageUrl">
              <el-input v-model="errorTestForm.imageUrl" placeholder="请输入图片链接,多个链接间用英文逗号分隔,请不要输入空格与汉字"
                type="textarea" @input="inputValueChange" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="图片上传">
              <el-upload class="upload-demo" ref="upload" action="/" :on-change="changeErrorTestFile"
                :on-preview="handlePreview" :file-list="errorTest_file_list" multiple :auto-upload="false"
                list-type="picture-card">
                <div slot="file" slot-scope="{file}" class='uploadImg'>
                  <img class="el-upload-list__item-thumbnail" style="width: 100%;height: 100%;" :src="file.url" alt>
                  <span class="el-upload-list__item-actions">
                    <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
                      <i class="el-icon-zoom-in"></i>
                    </span>
                    <span class="el-upload-list__item-delete" @click="handleDownloadFile(file)">
                      <i class="el-icon-download"></i>
                    </span>
                    <span class="el-upload-list__item-delete" @click="handleRemove(file)">
                      <i class="el-icon-delete"></i>
                    </span>
                  </span>
                </div>
                <el-button slot="trigger" size="small" type="primary">上传图片</el-button>
              </el-upload>
            </el-form-item>
          </el-col>
          <!-- <el-col :span="24">
            <el-form-item label="图片上传" prop="packageFile">
              <el-upload class="upload-demo" ref="upload" action="/" :on-change="changeFile" :on-preview="handlePreview"
                :on-remove="handleRemove" :file-list="fileList" multiple :auto-upload="false" list-type="picture-card">
                <el-button slot="trigger" size="small" type="primary">上传图片</el-button>
              </el-upload>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="图片URL" prop="imageUrl">
              <el-input v-model="errorTestForm.imageUrl" placeholder="识别多张时，url以英文逗号分开 如 a.img,b.png" />
            </el-form-item>
          </el-col> -->
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancel">取 消</el-button>
        <el-button type="primary" @click="confirmErrorTest">识 别</el-button>
      </div>
    </el-dialog>

    <!-- 算法识别弹窗 -->
    <el-dialog :title="dialogTitle" :visible.sync="dialogOpen" :close-on-click-modal="false" @close="cancel"
      width="800px" append-to-body>
      <el-form ref="recognitionForm" :model="recognitionForm" :rules="recognitionFormRules" label-width="120px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="项目" prop="projectId">
              <el-select v-model="recognitionForm.projectId" clearable filterable placeholder="请选择">
                <el-option v-for="item in project_list" :key="item.id" :label="item.name" :value="item.id">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="图片上传" prop="packageFile">
              <input type="file" ref="packageFile" @change="handFileChange" />
              <img style="width: 100px" :src="picUrl" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="图片URL" prop="imageUrl">
              <el-input v-model="recognitionForm.imageUrl" placeholder="请输入" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancel">取 消</el-button>
        <el-button type="primary" @click="uploadImg">识 别</el-button>
      </div>
    </el-dialog>

    <!-- 风幕算法识别弹窗 -->
    <el-dialog :title="irregularFigureDialogTitle" :visible.sync="irregularFigureDialogOpen"
      :close-on-click-modal="false" @close="cancel" width="800px" append-to-body>
      <el-form ref="irregularFigureForm" :model="irregularFigureForm" label-width="120px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="项目" prop="projectId" required>
              <el-select v-model="irregularFigureForm.projectId" clearable filterable placeholder="请选择">
                <el-option v-for="item in project_list" :key="item.id" :label="item.name" :value="item.id">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="方向" prop="direction" required>
              <el-select v-model="irregularFigureForm.direction" placeholder="请选择" clearable @change="changeDirection">
                <el-option
                  v-for="dict in dict.type.direction_type"
                  :key="dict.value"
                  :label="dict.label"
                  :value="dict.value"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="风幕柜类型" prop="containerType" required>
              <el-select v-model="irregularFigureForm.containerType" clearable filterable placeholder="请选择">
                <el-option v-for="item in containerType_list" :key="item.code" :label="item.containerType"  :value="item.code">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="图片上传" prop="packageFile">
              <input type="file" ref="segPackageFile" @change="handIrregularFigureFileChange" />
              <img style="width: 100px" :src="picUrl" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="图片URL" prop="urlPath">
              <el-input v-model="irregularFigureForm.urlPath" placeholder="请输入" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancel">取 消</el-button>
        <el-button type="primary" @click="irregularFigureRecognise">识 别</el-button>
      </div>
    </el-dialog>




    <el-dialog title="识别结果" :visible.sync="logDialog" :close-on-click-modal="false" width="75%" destroy-on-close
      destroy-on-closescope>
      <span>算法名称：{{ this.algorithm }}</span>
      <span style="margin-left:15px">算法版本：{{ this.version }}</span>
      <!-- <el-button
        style="margin-bottom: 10px"
        size="small"
        @click="handleDownload"
        icon="el-icon-download"
        >下载当前截取的小图</el-button
      > -->
      <div class="analy-container" style="height: auto;width: 100%;">
        <div ref="canvasBox" style="float: left;">
          <canvas ref="canvas"></canvas>
        </div>
        <div ref="canvasClickBox"
          style="border:1px solid red;width: 600px;height: 600px;margin-left:10%;margin-top: 20%;float: left;">
          <div>算法skuId：
            <el-select v-model="alogSkuId" placeholder="请选择要添加小图的算法" clearable filterable>
              <el-option v-for="item in arithmetic_list" :key="item.id"
                :label="item.id + '-' + item.name + ' (' + (item.layer === 1 ? '顶' : (item.layer === 2 ? '中间' : '底')) + ')'"
                :value="item.id" />
            </el-select>
            <el-button size="mini" type="text" @click="handleAdd()" style="margin-left: 20px;">新增小图</el-button>
            <el-button size="mini" type="text" @click="handleDownload()" style="margin-left: 20px;">下载截取图片</el-button>
          </div>
          <div style="width: 600px;height: 500px;">
            <div style="width: 50%;height: 100%;float: left;">
              截取的图片：
              <canvas id="canvasSingle" ref="canvasSingle" width="300" height="300"></canvas>
            </div>
            <div style="width: 49%;height: 100%;float: left;position: relative;">
              <div>主图：</div>
              <div><img :src="this.nowMainPicUrl" style="max-width: 100%;height: auto;"></div>
              <div style="float: left;margin-top: 10px;height: 20px;line-height: 20px;">{{ this.nowMainPicName }}</div>
            </div>
          </div>
        </div>
      </div>


      <!-- 陈列明细 -->
      <el-table :data="skuList" style="width: 100%">
        <el-table-column label="sku名称" prop="skuName" align="center">
        </el-table-column>
        <el-table-column label="所在层数" prop="skuLayer" align="center">
        </el-table-column>
        <el-table-column label="排面数量" prop="skuNum" align="center">
        </el-table-column>
        <el-table-column label="排面占比" prop="skuRate" align="center">
        </el-table-column>
      </el-table>

      <span slot="footer" class="dialog-footer">
        <el-button @click="logDialog = false">取 消</el-button>
        <el-button type="primary" @click="logDialog = false">确 定</el-button>
      </span>
    </el-dialog>

    <el-dialog title="不规则图形绘制结果" :visible.sync="irregularFigureResultDialogOpen" :close-on-click-modal="false"
    @close="cancel" width="75%" destroy-on-close destroy-on-closescope>
    <div class="analy-container" style="height: 1000px;width: 100%;">
      <div ref="irregularFigureCanvasBox" style="float: left;">
        <canvas ref="canvas"></canvas>
      </div>
    </div>
  </el-dialog>

    <!-- 弹框-新增小图 -->
    <el-dialog :title="AlgoDialogTitle" :visible.sync="AlgoDialogOpen" @close="cancel" width="800px" append-to-body>
      <el-form ref="algoForm" :model="algoForm" label-width="120px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="SKU名称" prop="skuName">
              <el-input v-model="algoForm.skuName" placeholder="请输入" @input="inputValueChange" type="text"
                maxlength="32" show-word-limit />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="特征库层" prop="layer">
              <el-select clearable="" v-model="algoForm.layer" filterable placeholder="请选择层">
                <el-option v-for="item in layerList" :key="item.id" :label="item.name" :value="item.id">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="V4算法主图" prop="algMainImg">
              <input type="file" ref="algMainImg" @change="handldAlgMainImgChange" />
              <img style="width: 100px" :src="mainImgUrl" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="当前小图总数:">
              <span>{{ this.minImgListSum }}</span>
            </el-form-item>
            <!-- <el-form-item  >
              <el-button type="primary" @click="delMinImgList" >一键清空小图</el-button>
            </el-form-item> -->
            <el-form-item>
              <el-button type="primary" @click="addCutPic">加入当前截取图片</el-button>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="小图组" prop="algMinImgList">
              <el-upload :disabled="true" class="upload-demo" ref="upload" action="/" :on-change="changeFile"
                :on-preview="handlePreview" :file-list="fileList" multiple :auto-upload="false"
                list-type="picture-card">
                <el-button slot="trigger" size="small" type="primary">上传图片</el-button>
              </el-upload>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="handleCancelAdd">取 消</el-button>
        <el-button type="primary" @click="submitForm">确 定</el-button>
      </div>
    </el-dialog>

    
    <!-- 异常检测阈值设置-弹框 -->
    <el-dialog title="异常检测阈值设置" :visible.sync="errorThresholdSetdialogOpen" @close="cancel" width="800px" append-to-body>
      <el-form :model="errorThresholdSetForm" label-width="120px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="异常类型" prop="errorType">
              <el-select v-model="errorThresholdSetForm.errorType" clearable filterable placeholder="请选择">
                <el-option v-for="item in errorType_list" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="阈值" prop="threshold">
              <el-input v-model="errorThresholdSetForm.threshold" placeholder="请输入阈值" @input="inputValueChange" type="number" oninput="if(value > 100)value = 100;if(value<0)value = 0" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancel">取 消</el-button>
        <el-button type="primary" @click="confirmSetErrorThreshold">确 定</el-button>
      </div>
    </el-dialog>

    <!-- v5陈列算法测试-弹框 -->
    <el-dialog title="v5陈列算法测试" :visible.sync="v5DialogOpen" :close-on-click-modal="false" @close="cancel"
      width="800px" append-to-body>
      <el-form ref="v5Form" :model="v5Form" label-width="120px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="项目" prop="projectId">
              <el-select v-model="v5Form.projectId" clearable filterable placeholder="请选择">
                <el-option v-for="item in project_list" :key="item.id" :label="item.name" :value="item.id">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="算法模型" prop="model">
              <el-select v-model="v5Form.model" clearable filterable placeholder="请选择">
                <el-option
                  v-for="dict in dict.type.algo_v5_model"
                  :key="dict.value"
                  :label="dict.label"
                  :value="dict.value"
                />
              </el-select>
              
            </el-form-item>
          </el-col>
          <!-- <el-col :span="24">
            <el-form-item label="冰柜类型序号" prop="containerType">
              <el-select v-model="v5Form.containerType" clearable filterable placeholder="请选择">
                <el-option v-for="item in containerType_list" :key="item.id" :label="item.name" :value="item.id">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col> -->
          <el-col :span="24">
            <el-form-item label="图片上传" prop="packageFile">
              <input type="file" ref="v5PackageFile" @change="v5FileChange" />
              <img style="width: 100px" :src="picUrl" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="图片URL" prop="urlPath">
              <el-input v-model="v5Form.urlPath" placeholder="请输入" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancel">取 消</el-button>
        <el-button type="primary" @click="v5Recognise">识 别</el-button>
      </div>
    </el-dialog>

    <el-dialog title="v5陈列算法结果" :visible.sync="v5ResultDialogOpen" :close-on-click-modal="false" width="75%"
      @close="cancel" destroy-on-close destroy-on-closescope>
      <div class="analy-container" style="height: 1000px;width: 100%;">
        <div ref="v5CanvasBox" style="float: left;">
          <canvas ref="v5canvas"></canvas>
        </div>
      </div>
    </el-dialog>

    <!-- 图片放大 -->
    <el-dialog :visible.sync="dialogVisible">
      <img width="100%" :src="dialogImageUrl" alt="">
    </el-dialog>


  </div>
</template>

<script>
import { setInitImg } from '@/utils/url-transfer-file'
import { fabric } from 'fabric'
import { coverRecognize, muddyRecognize, brightnessRecognize, setCoverThreshold, setMuddyThreshold, setBrightnessThreshold} from '@/api/arithmetic/arithmetic-error-Test';
import { algV4Detect, getAlgListV4, getArithmeticDetail, modifySkuMinImgList, shelterRecognize, setShelterThresholdV4 } from '@/api/arithmetic/arithmetic';
import { listProject } from "@/api/project/project";
import { listSku } from "@/api/sku/sku";
import { segRecognize } from "@/api/genius/platform-seg-algo-v1";
import { listSegBaseSku } from "@/api/segmentation/seg-base-sku";
import { v5Recognize, listDisplayAlgoV5 } from "@/api/genius/platform-display-algo-v5";
import { listSegContainerType} from "@/api/segmentation/seg-container-type-config";

export default {
  dicts: ['direction_type','algo_v5_model'],
  data() {
    return {
      errorThresholdSetForm:{
        threshold:'',
        errorType:''
      },
      errorThresholdSetdialogOpen:false,
      // 算法识别结果
      seg_algo_result: [],
      // 算法id-商品名称对应关系
      SegBaseSkuList: [],
      point_list: [],
      point_list2: [],
      uploadPicNum: 0, //上传的图片数量
      dialogImageUrl: '',//放大图片的url
      dialogVisible: false,//点击放大
      takeType_list:[
        {
          value: false,
          label: '否'
        },
        {
          value: true,
          label: '是'
        }
      ],
      errorType_list:[
        {
          value: 'cover',
          label: '遮挡'
        },
        {
          value: 'muddy',
          label: '油污'
        },
        {
          value: 'brightness',
          label: '曝光'
        }
      ],
      layerList: [
        {
          name: '顶层库',
          id: 1
        },
        {
          name: '中间层库',
          id: 2
        },
        {
          name: '底层库',
          id: 3
        },
      ],
      skuSum: 0,
      skuList: [],
      fileList: [], // 小图集合 
      errorTest_file_list: [], // 遮挡图片集合 
      algorithm: '',//算法名称
      version: '',//算法版本
      currentLog: null, // 当前查看的识别记录
      logDialog: false,
      v5DialogOpen: false,//v5成列算法弹窗
      v5Form: {
        projectId: '', // 项目id
        urlPath: '', // 输入的图片url
        packageFile: '', // 上传图片文件
        containerType: 1, // 冰柜类型序号
        model:null  // 算法模型
      },
      v5Algoresult: '',
      v5ResultDialogOpen: false,
      //表单校验
      algoFormRules: {
        skuName: [{ required: true, message: '请选择', trigger: 'blur' }],
        algMainImg: [{ required: true, message: '请选择', trigger: 'blur' }],
      },
      // 算法列表
      arithmetic_list: [],
      alogSkuId: '',//输入的算法skuId
      loading: false,//新增
      //算法详情表单
      algoForm: {
        skuName: '',
        algMainImg: '',
        layer: '',
        algMinImgList: [],
      },
      v5SkuList: [],
      AlgoDialogTitle: "算法详情",
      addMark: false,
      AlgoDialogOpen: false,
      nowAddFile: '',
      nowMainPicName: '',//当前对应的sku的名称
      imgHeight: 0,
      nowMainPicUrl: '',//当前对应的sku的主图url
      skuPosition: 0,
      nowAddUrl: '',//截取的图片的url
      cutPicNum: 0,
      minImgListSum: 0,//小图组总数
      mainImgUrl: '',//主图url
      number: 0,
      // 商品列表
      sku_list: [],
      // 项目列表
      project_list: [],
      containerType_list: [],
      editRecResultForm:{
        result:''
      },
      // 异常检测-表单字段
      errorTestForm: {
        threshold:50,//阈值
        errorType: '', // 项目id
        imageUrl: '', // 输入的图片url
        packageFile: '' // 上传图片文件
      },
      errorTestdialogOpen: false,
      // 算法识别-表单字段
      recognitionForm: {
        projectId: '', // 项目id
        imageUrl: '', // 输入的图片url
        packageFile: '' // 上传图片文件
      },
      irregularFigureForm: {
        projectId: '', // 项目id
        urlPath: '', // 输入的图片url
        packageFile: '', // 上传图片文件
        direction:'',
        containerType: '' // 冰柜类型序号
      },
      // 识别结果弹窗展示的图片
      showUrl: '',
      // 图片文件上传的url
      picUrl: '',
      // 算法识别-表单校验规则
      recognitionFormRules: {
        projectId: [{ required: true, message: '请选择', trigger: 'blur' }]
      },
      shelterJudgeFormRules: {
        projectId: [{ required: true, message: '请选择', trigger: 'blur' }]
      },
      //识别结果类型： userResult allResult
      resultType: '',
      // 油污算法版本号
      oilStainVersion: '',
      // 油污阈值弹窗
      oilStainValueSettingDialogOpen: false,
      // 油污弹窗
      oilStainDialogOpen: false,
      // 遮挡阈值表单
      shelterValueSettingForm: {
        projectId: ''
      },
      // 遮挡阈值弹窗
      shelterValueSettingDialogOpen: false,
      // 遮挡弹窗
      shelterDialogOpen: false,
      // 算法识别-弹窗标题
      dialogTitle: '图片上传',
      irregularFigureDialogTitle: '不规则图形绘制测试弹窗',
      // 绘制不规则图形-弹窗开关
      irregularFigureDialogOpen: false,
      // 修改算法识别结果弹窗
      editRecResultDialogOpen: false,
      result_list:[],
      containerType_list:[],
      // 绘制不规则图形-弹窗开关
      irregularFigureResultDialogOpen: false,
      // 算法识别-弹窗开关
      dialogOpen: false,
      // 油污分数判断-表单字段
      oilStainJudgeForm: {
        userId: '',  //用户id
        twoUserId: '',
        threeUserId: '',
        fourUserId: '',
        fiveUserId: '',
        sixUserId: '',
        packageFile: '',
        imageUrl: '',
        picUrl: ''
      },
      timer: null,//定时器
      // 遮挡分数判断-表单字段
      shelterJudgeForm: {
        projectId: '', // 项目id
        threshold: '', // 阈值
        imageUrl: '', // 需要识别的图片地址，多个以英文逗号字符分割，url中请勿存在中文或空格
      },

    }
  },

  methods: {
    // 点击-检测阈值设置
    handleErrorThresholdSet(){
      this.errorThresholdSetForm = {
        threshold: '',//阈值
        errorType: '', // 项目id
      };
      this.errorThresholdSetdialogOpen = true;
    },
    // 点击-图片异常检测按钮
    handleErrorTest(){
      this.errorTest_file_list = [];
      this.uploadPicNum = 0;
      this.errorTestForm = {
        threshold:50,//阈值
        errorType: '', // 项目id
        imageUrl: '', // 输入的图片url
        packageFile: '' // 上传图片文件
      };
      this.errorTestdialogOpen = true;
    },
    /** 选择方向 */
    changeDirection(){
      const params = {
        pageNum: 1,
        pageSize: 10000,
        direction:this.irregularFigureForm.direction
      }
      listSegContainerType(params).then(response => {
        if (response.code === 200) {
          this.containerType_list = response.rows;
          // if (this.containerType_list.length > 0) {
          //   this.irregularFigure.containerType = this.containerType_list[0].id;
          // }
        } else {
          this.$message.error("接口调用失败,原因：" + response.msg)
        }
      }).finally(() => {
        this.loading = false;
      });
    },
    /** 获取风幕柜商品列表（算法id和商品name的对应关系） */
    getSegSkuList() {
      const params = {
        pageNum: 1,
        pageSize: 10000,
        soId: null,
        name: null,
        removed: null
      };
      listSegBaseSku(params).then((response) => {
        if (response.code === 200) {
          this.SegBaseSkuList = response.data.data;
        } else {
          this.$message.error("风幕柜商品列表接口调用失败,原因：" + response.msg)
        }
      }).finally(() => {
        this.drawIrregular();
      })
    },
    /** 获取v5商品列表（算法id和商品name的对应关系） */
    getv5SkuList() {
      const params = {
        pageIndex: 1,
        pageSize: 10000,
        soId: null,
        skuName: null,
      };
      listDisplayAlgoV5(params).then((response) => {
        if (response.code === 200) {
          this.v5SkuList = response.data.data;
        } else {
          this.$message.error("陈列v5算法商品列表接口调用失败,原因：" + response.msg)
        }
      }).finally(() => {
        this.drawv5egular();
      })
    },
    /** 确定设置异常检测阈值 */
    confirmSetErrorThreshold(){
      if(!this.errorThresholdSetForm.errorType){
        this.$message.warning("请选择您要设置的异常检测类型！");
        return;
      }
      if (!this.errorThresholdSetForm.threshold) {
        this.$message.warning("请输入您想设置的阈值！");
        return;
      }
      const param = {
        threshold: parseInt(this.errorThresholdSetForm.threshold)
      }
      if(this.errorThresholdSetForm.errorType == 'cover'){
        setCoverThreshold(param).then((res) =>{
          if (res.code === 200) {
          this.$message.success("遮挡阈值设置成功！")
          }
        }).catch((err) => {
          this.$message.error("遮挡阈值设置失败！原因：" + err.message)
        }).finally(() => {
          this.errorThresholdSetdialogOpen = false
        })
      }else if(this.errorThresholdSetForm.errorType == 'muddy'){
        setMuddyThreshold(param).then((res) =>{
          if (res.code === 200) {
          this.$message.success("油污阈值设置成功！")
          }
        }).catch((err) => {
          this.$message.error("油污阈值设置失败！原因：" + err.message)
        }).finally(() => {
          this.errorThresholdSetdialogOpen = false
        })
      }else if(this.errorThresholdSetForm.errorType == 'brightness'){
        setBrightnessThreshold(param).then((res) =>{
          if (res.code === 200) {
          this.$message.success("曝光阈值设置成功！")
          }
        }).catch((err) => {
          this.$message.error("曝光阈值设置失败！原因：" + err.message)
        }).finally(() => {
          this.errorThresholdSetdialogOpen = false
        })
      }

    },
    /** 确认设置遮挡算法阈值 */
    confirmSetShelterValue() {
      if (!this.shelterValueSettingForm.threshold) {
        this.$message.warning("请输入您想设置的阈值！")
        return
      }
      const param = {
        threshold: parseInt(this.shelterValueSettingForm.threshold)
      }
      setShelterThresholdV4(param).then((res) => {
        if (res.code === 200) {
          this.$message.success("阈值设置成功！")
        }
      }).catch((err) => {
        this.$message.error("设置失败！原因：" + err.message)
      }).finally(() => {
        this.shelterValueSettingDialogOpen = false
      })
    },
    /** 上传图片-删除 */
    handleRemove(file) {
      var index = this.errorTest_file_list.indexOf(file)
      if (index !== -1) {
        // this.algoForm.files.splice(index,1)
        this.errorTest_file_list.splice(index, 1)
      }
    },
    /** 图片下载 */
    handleDownload() {
      var file = this.nowAddFile;
      var link = document.createElement("a"); //定义一个a标签
      link.download = file.name; //下载后的文件名称
      let href = URL.createObjectURL(file);//获取url
      link.href = href; //需要生成一个 URL 来实现下载
      link.click(); //模拟在按钮上实现一次鼠标点击
      window.URL.revokeObjectURL(link.href);
    },
    /** 图片下载 */
    handleDownloadFile(file) {
      var link = document.createElement("a"); //定义一个a标签
      link.download = file.name; //下载后的文件名称
      let href = URL.createObjectURL(file);//获取url
      link.href = href; //需要生成一个 URL 来实现下载
      link.click(); //模拟在按钮上实现一次鼠标点击
      window.URL.revokeObjectURL(link.href);
    },
    /** 图片放大 */
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    },
    /** base64转文件 */
    base64ToFile(base64, fileName) {
      let arr = base64.split(",");
      // let mime = arr[0].match(':')[1];
      let mime = 'image/png'
      let bstr = atob(arr[1]);
      let n = bstr.length;
      let u8arr = new Uint8Array(n);

      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], fileName, { type: mime });
    },
    /** 获取算法列表 */
    getAlgoData() {
      const params = {
        pageIndex: 0,
        pageSize: 10000,
        // skuId : this.skuId,
        // layer:0
      }
      getAlgListV4(params)
        .then((res) => {
          this.arithmetic_list = res.data.data
        }).catch((err) => {
          this.$message.error("算法列表获取失败", err.message)
        })
        .finally(() => {

        })
    },
    /** 确认新增小图 */
    submitForm() {
      if (this.algoForm.skuName == '') {
        this.$confirm('请输入sku名称', '提示', {
          distinguishCancelAndClose: true,
          confirmButtonText: '确认',
          cancelButtonText: '取消',
        })
      }

      if (this.algoForm.algMainImg == '') {
        this.$confirm('请上传主图', '提示', {
          distinguishCancelAndClose: true,
          confirmButtonText: '确认',
          cancelButtonText: '取消',
        })
      }
      if (this.addMark === false) {
        this.$confirm('请先点击按钮-加入当前截取图片', '提示', {
          distinguishCancelAndClose: true,
          confirmButtonText: '确认',
          cancelButtonText: '取消',
        })
        return
      }
      setInitImg(this.algoForm.packageFile, (file) => {
        this.algoForm.packageFile = file
        const form = this.algoForm
        const formData = new FormData()
        for (var i = 0; i < form.files.length; i++) {
          formData.append("files", form.files[i])
        }
        const params = {
          skuId: form.skuId,
          files: formData
        }
        this.uploadLoading = true
        this.$notify({
          title: '提示',
          message: '图片上传中,请稍后…',
          offset: 700,
          duration: 0
        });
        this.dialogFull = true
        modifySkuMinImgList(params).then((res) => {
          this.$message.success('新增小图成功')
          this.$notify.closeAll();//去掉交互框
          this.AlgoDialogOpen = false
        })
          .catch((err) => {
            this.$message.error(err.message)
          })
          .finally(() => {
            this.dialogFull = false
            this.uploadLoading = false
          })
      })
    },
    /** 加入截取图片 */
    addCutPic(file, fileList) {
      if (this.nowAddFile) {
        this.algoForm.files.push(this.nowAddFile)
        this.addMark = true
        this.minImgListSum++
        this.algoForm.algMinImgList.push(this.nowAddUrl)
        let temp = {
          name: this.nowAddUrl,
          url: this.nowAddUrl,
          status: 'ready',
          uid: this.cutPicNum
        }
        this.cutPicNum++
        this.fileList.push(temp)
        this.$forceUpdate()
      } else {
        this.$message.info("请先选择一张小图")
        this.AlgoDialogOpen = false
      }


    },
    handldAlgMainImgChange(e) {
      let fileData = e.target.files[0] //这是我们上传的文件
      this.algoForm.algMainImg = fileData
      this.algoForm.packageFile = fileData
      let url = URL.createObjectURL(fileData)
      this.mainImgUrl = url
    },
    changeErrorTestFile(file, fileList) {
      // 限制上传的图片类型
      if (file.raw.type == 'image/jpeg' || file.raw.type == 'image/png') {
        this.errorTest_file_list = fileList
        this.uploadPicNum = this.errorTest_file_list.length
        // 限制最大上传张数
        if (this.uploadPicNum > 200) {
          // 防抖
          if (this.timer) {
            // 次数>1时，清空之前的定时器
            clearTimeout(this.timer)
            this.timer = setTimeout(() => {
              this.$message.warning("当前仅支持200张同时识别，已删除第201张及之后的图片")
            }, 1000)
          } else {
            // 第一次
            this.timer = setTimeout(() => {
              this.$message.warning("当前仅支持200张同时识别，已删除第201张及之后的图片")
            }, 1000)
          }
          this.errorTest_file_list.splice(200, 1)
          this.uploadPicNum = this.errorTest_file_list.length
        }
      } else {
        this.$message.warning("当前仅支持jpg和png格式的图片")
        var index = this.errorTest_file_list.indexOf(file)
        this.errorTest_file_list.splice(index, 1)
      }
    },
    changeFile(file, fileList) {
      let fileData = file.raw
      if (this.dialogTitle == '小图情况') {
        this.algoForm.files.push(fileData)
        this.minImgListSum++
      } else {
        this.algoForm.algMinImgList.push(fileData)
        this.minImgListSum++
      }
    },
    handlePreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    },
    /** 输入框强制刷新 */
    inputValueChange() {
      this.$forceUpdate()
    },
    /** 点击取消新增小图按钮 */
    handleCancelAdd() {
      this.AlgoDialogOpen = false
      this.algoForm = {}
    },
    /** 点击新增小图按钮 */
    handleAdd() {
      if (!this.alogSkuId) {
        this.$message.warning("请先选择算法")
        return
      }

      //初始化
      this.mainImgUrl = ''
      this.fileList = []
      this.minImgListSum = 0
      this.algoForm = {}
      this.AlgoDialogOpen = true
      this.addMark = false
      //todo根据skuid调用接口获取算法详情和小图信息
      const params = {
        skuId: this.alogSkuId
      }
      getArithmeticDetail(params)
        .then((res) => {
          let resData = res.data
          //初始化数据
          this.algoForm.skuName = resData.name
          this.mainImgUrl = resData.packageUrl
          this.algoForm.layer = resData.layer
          this.algoForm.algMinImgList = resData.pics
          this.algoForm.algMainImg = resData.packageUrl
          this.algoForm.packageFile = resData.packageUrl
          this.minImgListSum = resData.imageCount
          this.algoForm.imgList = resData.pics
          //upload组件需要name属性才能加载
          this.fileList = this.algoForm.imgList.map(item => {
            return {
              name: item,
              url: item
            }
          });
          //小图组url转file
          this.algoForm.imgList.forEach((item) => {
            setInitImg(item, (file) => {
              this.algoForm.files.push(file)
            })
          })
        }).catch((err) => {
          this.$message.error("获取算法详情失败", err.message)
        })
        .finally(() => {

        })

      this.algoForm.skuId = this.alogSkuId

      //用于存放小图组files
      this.algoForm.files = []
      //主图url转file
      setInitImg(this.algoForm.packageFile, (file) => {
        this.algoForm.packageFile = file
        // this.fileList.push(file)
      })
    },
    /** 图片遮挡-判断 */
    async judgeShelter() {
      if (!this.shelterJudgeForm.projectId) {
        this.$confirm(`请选择项目`, '提示', {
          confirmButtonText: '确定',
          showCancelButton: false,
          type: 'warning',
        })
        return
      }
      if (!this.shelterJudgeForm.threshold) {
        this.$confirm(`请输入阈值`, '提示', {
          confirmButtonText: '确定',
          showCancelButton: false,
          type: 'warning',
        })
        return
      }
      if (this.errorTest_file_list.length === 0 && this.shelterJudgeForm.imageUrl == '') {
        this.$confirm(`请上传图片或填写图片链接`, '提示', {
          confirmButtonText: '确定',
          showCancelButton: false,
          type: 'warning',
        })
        return
      }


      const formData = new FormData()
      this.errorTest_file_list.map((item) => {
        formData.append('images', item.raw)
      })
      this.$notify({
        title: '提示',
        message: '判断遮挡中…',
        offset: 700,
        duration: 0
      });
      const params = {
        projectId: this.shelterJudgeForm.projectId,
        threshold: this.shelterJudgeForm.threshold,
        imageUrl: this.shelterJudgeForm.imageUrl,
        images: formData
      }
      shelterRecognize(params).then((res) => {
        if (res.code === 200) {
          let text = ''
          let shelterNum = 0
          for (var i = 0; i < res.data.length; i++) {
            // 遮挡红字，正常绿字
            let color = (res.data[i].label == '遮挡' ? 'red' : 'green')
            // 统计遮挡次数
            if (res.data[i].label == '遮挡') {
              shelterNum++
            }
            text = text + `<p>图片${i + 1}:${res.data[i].imageName + '——————————分数:' + `<span style="color:${color}">${res.data[i].score}</span>` + '分——————————结论：' + `<span style="color:${color}">${res.data[i].label}。</span>`}</p>`
          }
          text = '<p style="font-size:16px;color:#2491fc">共识别 ' + res.data.length + ' 张图片，其中遮挡 ' + shelterNum + ' 张,正常 ' + (res.data.length - shelterNum) + ' 张。<p>' +
            '<p">详细识别结果如下:</p>' + text
          this.$confirm(text, '遮挡识别结果', {
            confirmButtonText: '确定',
            dangerouslyUseHTMLString: true,
            showCancelButton: false,
            type: 'success',
          })
        }
      }).catch((err) => {
        this.$message.error("判断失败！原因：" + err.message)
      }).finally(() => {
        this.$notify.closeAll();//去掉交互框
      })

    },
    /** 获取商品列表 */
    getSkuList() {
      const req = listSku({
        pageIndex: 0,
        pageSize: 10000
      })
        .then((res) => {
          if (res && res.total > 0) {
            this.sku_list = res.rows
          }
        }).catch((err) => {
          this.$message.error("商品获取失败！", err.message)
        })
    },
    irregularFigureRecognise() {
      // 校验是否选择了项目
      if (!this.irregularFigureForm.projectId) {
        this.$message.warning("请选择项目");
        return;
      }
      // 校验是否上传了图片
      if (this.irregularFigureForm.urlPath == '' && this.irregularFigureForm.packageFile == '') {
        this.$confirm(`请上传图片或者填写图片URL(二选一)`, '提示', {
          confirmButtonText: '确定',
          showCancelButton: false,
          type: 'warning',
        });
        return;
      }
      // 判断是哪种方式上传图片
      if (this.irregularFigureForm.packageFile) {
        this.showUrl = this.picUrl
      } else {
        this.showUrl = this.irregularFigureForm.urlPath
      }
      // 参数处理
      const form = this.irregularFigureForm
      let str = ''
      const formData = new FormData()
      formData.append('projectId', form.projectId);
      formData.append('containerType', form.containerType);
      formData.append('imageFile', form.packageFile);
      formData.append("urlPath", form.urlPath);
      formData.append('direction',form.direction);
      const params = {
        url: str,
        file: formData
      }
      this.$notify({
        title: '提示',
        message: '图片识别中,请稍后…',
        offset: 700,
        //duration: 0
      });
      //this.$notify.close()
      // 调用识别接口
      segRecognize(params).then((res) => {
        // 之后result替换成res
        if (res.code === 200) {
          if (!res.data || res.data.length === 0) {
            this.$message.error("识别结果长度为0");
            return
          }
          this.seg_algo_result = res.data;
          // 1.去掉交互框
          this.$notify.closeAll();
          // 2.打开弹框
          this.irregularFigureResultDialogOpen = true;
          // 3.获取风幕柜商品对应关系
          this.getSegSkuList();
        }
      }).catch((err) => {
        this.$message.error("识别失败！原因：", err.message)
      })
    },
    /**v5陈列算法识别检测 */
    v5Recognise() {
      // 校验是否选择了项目
      if (!this.v5Form.projectId) {
        this.$message.warning("请选择项目");
        return;
      }
      // 校验是否上传了图片
      if (this.v5Form.urlPath == '' && this.v5Form.packageFile == '') {
        this.$confirm(`请上传图片或者填写图片URL(二选一)`, '提示', {
          confirmButtonText: '确定',
          showCancelButton: false,
          type: 'warning',
        });
        return;
      }
      // 判断是哪种方式上传图片
      if (this.v5Form.urlPath) {
        this.picUrl = this.v5Form.urlPath
      }
      // 参数处理
      const form = this.v5Form
      let str = ''
      const formData = new FormData()
      Object.keys(form).forEach(key => {
        if (key == 'packageFile') {
          formData.append('imageFile', form[key]);
        } else {
          formData.append(key, form[key]);
        }
      })
      const params = {
        url: str,
        file: formData
      }
      this.$notify({
        title: '提示',
        message: '图片识别中,请稍后…',
        offset: 700,
        //duration: 0
      });
      // 调用识别接口
      v5Recognize(params).then((res) => {
        if (res.code === 200) {
          if (!res.data || res.data.length === 0) {
            this.$message.error("识别结果长度为0");
            return
          }
          this.v5Algoresult = res.data.outputJniSegs;
          // 1.去掉交互框
          this.$notify.closeAll();
          // 2.打开弹框
          this.v5ResultDialogOpen = true;
          // 3.获取风幕柜商品对应关系
          this.getv5SkuList();
          //this.cancel()
        }
      }).catch((err) => {
        this.$message.error("识别失败！原因：", err.message)
      })
    },
    /** 异常检测-接口调用 */
    confirmErrorTest(){
      // 校验
      if((this.errorTestForm.imageUrl == '') && (this.errorTest_file_list.length === 0)){
        this.$confirm(`请上传图片或者填写图片URL(二选一)`, '提示', {
            confirmButtonText: '确定',
            showCancelButton: false,
            type: 'warning',
          })
          return;
      }else if(!this.errorTestForm.errorType){
        this.$message.warning("请选择异常类型")
        return;
      }else if(!this.errorTestForm.threshold){
        this.$message.warning("请填写阈值")
        return;
      }
      // 参数处理
      const form = this.errorTestForm
      const formData = new FormData()
      this.errorTest_file_list.map((item) => {
        formData.append('images', item.raw)
      })
      // formData.append('images', fileArr);
      formData.append("imageUrl", form.imageUrl);
      formData.append('threshold',form.threshold);
      const params = {
        file: formData
      }
      this.$notify({
        title: '提示',
        message: '检测中,请稍后…',
        offset: 700,
        //duration: 0
      });
      // 调用接口
      if(this.errorTestForm.errorType == 'muddy'){ // 油污
        // 调用识别接口
        muddyRecognize(params).then((res) => {
          // 之后result替换成res
          if (res.code === 200) {
            if (!res.data || res.data.length === 0) {
              this.$message.error("识别成功，无返回结果");
              return
            }else{
              // 识别成功
              let text = ''
              let errorNum = 0
              for (var i = 0; i < res.data.length; i++) {
                // 遮挡红字，正常绿字
                // let color = (res.data[i].label == '遮挡' ? 'red' : 'green')
                let color = 'red'
                // 统计遮挡次数
                if (res.data[i].label == '油污') {
                  errorNum++
                }
                text = text + `<p>图片${i + 1}:${res.data[i].imageName + '——————————分数:' + `<span style="color:${color}">${res.data[i].score}</span>` + '分——————————结论：' + `<span style="color:${color}">${res.data[i].label}。</span>`}</p>`
              }
              text = '<p style="font-size:16px;color:#2491fc">共识别 ' + res.data.length + ' 张图片，其中油污 ' + errorNum + ' 张,正常 ' + (res.data.length - errorNum) + ' 张。<p>' +
                '<p">详细识别结果如下:</p>' + text
              this.$confirm(text, '油污识别结果', {
                confirmButtonText: '确定',
                dangerouslyUseHTMLString: true,
                showCancelButton: false,
                type: 'success',
              })
            }
            this.$notify.closeAll();
          }
        }).catch((err) => {
          this.$message.error("识别失败！原因：", err.message)
        })
      }else if(this.errorTestForm.errorType == 'cover'){ // 遮挡
        // 调用识别接口
        coverRecognize(params).then((res) => {
          // 之后result替换成res
          if (res.code === 200) {
            if (!res.data || res.data.length === 0) {
              this.$message.error("识别成功，无返回结果");
              return
            }else{
              // 识别成功
              let text = ''
              let errorNum = 0
              for (var i = 0; i < res.data.length; i++) {
                // 遮挡红字，正常绿字
                // let color = (res.data[i].label == '遮挡' ? 'red' : 'green')
                let color = 'red'
                // 统计遮挡次数
                if (res.data[i].label == '遮挡') {
                  errorNum++
                }
                text = text + `<p>图片${i + 1}:${res.data[i].imageName + '——————————分数:' + `<span style="color:${color}">${res.data[i].score}</span>` + '分——————————结论：' + `<span style="color:${color}">${res.data[i].label}。</span>`}</p>`
              }
              text = '<p style="font-size:16px;color:#2491fc">共识别 ' + res.data.length + ' 张图片，其中遮挡 ' + errorNum + ' 张,正常 ' + (res.data.length - errorNum) + ' 张。<p>' +
                '<p">详细识别结果如下:</p>' + text
              this.$confirm(text, '遮挡识别结果', {
                confirmButtonText: '确定',
                dangerouslyUseHTMLString: true,
                showCancelButton: false,
                type: 'success',
              })
            }
            this.$notify.closeAll();
          }
        }).catch((err) => {
          this.$message.error("识别失败！原因：", err.message)
        })
      }else if(this.errorTestForm.errorType == 'brightness'){ // 曝光
        // 调用识别接口
        brightnessRecognize(params).then((res) => {
          // 之后result替换成res
          if (res.code === 200) {
            if (!res.data || res.data.length === 0) {
              this.$message.error("识别成功，无返回结果");
              return
            }else{
              // 识别成功
              let text = ''
              let errorNum = 0
              for (var i = 0; i < res.data.length; i++) {
                // 遮挡红字，正常绿字
                // let color = (res.data[i].label == '遮挡' ? 'red' : 'green')
                let color = 'red'
                // 统计遮挡次数
                if (res.data[i].label == '曝光') {
                  errorNum++
                }
                text = text + `<p>图片${i + 1}:${res.data[i].imageName + '——————————分数:' + `<span style="color:${color}">${res.data[i].score}</span>` + '分——————————结论：' + `<span style="color:${color}">${res.data[i].label}。</span>`}</p>`
              }
              text = '<p style="font-size:16px;color:#2491fc">共识别 ' + res.data.length + ' 张图片，其中曝光 ' + errorNum + ' 张,正常 ' + (res.data.length - errorNum) + ' 张。<p>' +
                '<p">详细识别结果如下:</p>' + text
              this.$confirm(text, '曝光识别结果', {
                confirmButtonText: '确定',
                dangerouslyUseHTMLString: true,
                showCancelButton: false,
                type: 'success',
              })
            }
            this.$notify.closeAll();
          }
        }).catch((err) => {
          this.$message.error("识别失败！原因：", err.message)
        })
      }
    },
    /** 算法识别-接口调用 */
    uploadImg() {
      this.$refs.recognitionForm.validate((valid) => {
        // 校验是否选择了项目
        if (!valid) {
          return
        }
        // 校验是否上传了图片
        if (this.recognitionForm.imageUrl == '' && this.recognitionForm.packageFile == '') {
          this.$confirm(`请上传图片或者填写图片URL(二选一)`, '提示', {
            confirmButtonText: '确定',
            showCancelButton: false,
            type: 'warning',
          })
          return
        }
        // 判断是哪种方式上传图片
        if (this.recognitionForm.packageFile) {
          this.showUrl = this.picUrl
        } else {
          this.showUrl = this.recognitionForm.imageUrl
        }
        // 参数处理
        const form = this.recognitionForm
        let str = ''
        const formData = new FormData()
        Object.keys(form).forEach((key) => {
          if (key !== 'imageUrl' && key !== 'packageFile') {
            str += `&${key}=${form[key]}`
          }
        })
        formData.append('packageFile', form.packageFile)
        formData.append("imageUrl", form.imageUrl)
        const params = {
          url: str,
          file: formData
        }
        this.$notify({
          title: '提示',
          message: '图片识别中,请稍后…',
          offset: 700,
          //duration: 0
        });
        // 获取商品列表
        this.getSkuList()
        // 调用识别接口
        algV4Detect(params)
          .then((res) => {
            this.skuPosition = 0
            this.skuList = []
            this.logDialog = true
            if (res.code === 0) {
              this.$notify.closeAll();//去掉交互框
              if (this.resultType == 'userResult') {
                this.recognitionResult = res.data.userResult
              } else {
                this.recognitionResult = res.data.allResult
              }
              this.version = this.recognitionResult.version
              this.algorithm = this.recognitionResult.algorithm
              this.skuSum = this.recognitionResult.statistics.total_num
              //储存所有识别到sku，skuName为唯一字段
              let skuNameMap = new Map()
              this.recognitionResult.results.forEach((item) => {
                if (!skuNameMap.has(item.skuName)) {
                  skuNameMap.set(item.skuName, 1)
                } else {
                  skuNameMap.set(item.skuName, skuNameMap.get(item.skuName) + 1)
                }
              })
              //建立skuList模板
              for (var i = 0; i < skuNameMap.size; i++) {
                let temp = {
                  skuName: '',
                  skuNum: 0,
                  skuRate: '',
                  skuLayer: []
                }
                this.skuList.push(temp)
              }
              //skuList赋值1 - 名称、总量、占比
              skuNameMap.forEach((value, key, self) => {
                this.skuList[this.skuPosition].skuName = key
                this.skuList[this.skuPosition].skuNum = value
                this.skuList[this.skuPosition].skuRate = ((value / this.skuSum) * 100).toFixed(2) + '%'
                this.skuPosition++
              })
              //skuList赋值2 - 层数
              this.recognitionResult.results.forEach((res) => {
                for (var i = 0; i < this.skuList.length; i++) {
                  if (this.skuList[i].skuName == res.skuName && !this.skuList[i].skuLayer.includes(res.layer)) {
                    if (this.skuList[i].skuLayer.length !== 0) {
                      this.skuList[i].skuLayer.push(',')
                      this.skuList[i].skuLayer.push(res.layer)
                    } else {
                      this.skuList[i].skuLayer.push(res.layer)
                    }
                    // skuList[i].name = res.customerSkuName
                  }
                }
              })
            }
          }).catch((err) => {
            this.$message.error("识别失败！原因：", err.message)
          })
          .finally(() => {
            this.showLog() // canvas画布绘制
            this.getAlgoData() // 获取算法列表
          })
      })
    },
    //绘制v5不规则图形
    async drawv5egular() {
      //1.异步操作都在nextTick中返回
      this.$nextTick(() => {
        // const h = 500
        const h = 1000
        this.$refs.v5CanvasBox.style.height = h + 'px'
        //对图片进行渲染-图像文件的加载是异步的，所有对Image的后续操作都要在回调中完成
        fabric.Image.fromURL(
          this.picUrl,
          (img) => {
            let w
            img.set({ selectable: false })
            img.scaleToWidth(860)  //指定宽度
            img.scaleToHeight(1000)  //指定图片高度
            w = img.width * img.scaleX
            const canvas = new fabric.Canvas(this.$refs.v5canvas, {
              width: w,
              height: h,
              centeredRotation: true,
            })
            canvas.add(img)
            let results = []
            try {
              results = this.v5Algoresult || []
              // 用商品名替换掉算法名
              if (results.length > 0) {
                results.forEach((item) => {
                  this.v5SkuList.forEach((skuItem) => {
                    if (item.id == skuItem.soId) {
                      item.name = item.confidence.toFixed(2) + " " + skuItem.name + " " + item.confidence.toFixed(2)
                    }
                  })

                })
              }
            } catch (error) {
              console.log('商品名替换算法名', error);
            }
            let ids = []
            results.map(item => {
              ids.push(item.skuName)
            })
            ids = Array.from(new Set(ids))
            results.map(item => {
              for (var i = 0; i < ids.length; i++) {
                if (item.skuName == ids[i]) {
                  item.index = i
                }
              }
            })
            // 1 本品 绿色框 2 竞品 红色框 3 未知 蓝色框

            // 绘制不规则图形
            for (var i = 0; i < this.v5Algoresult.length; i++) {
              let loc = results[i]
              for (var k = 0; k < this.v5Algoresult[i].coordinate.length; k++) {
                var path = 'M'
                for (var q = 0; q < this.v5Algoresult[i].coordinate[k].length; q++) {
                  if (q === 0) {
                    path = path + " " + this.v5Algoresult[i].coordinate[k][q].x * img.scaleX + ' ' + this.v5Algoresult[i].coordinate[k][q].y * img.scaleY
                  } else {
                    path = path + ' L ' + this.v5Algoresult[i].coordinate[k][q].x * img.scaleX + ' ' + this.v5Algoresult[i].coordinate[k][q].y * img.scaleY
                  }
                }

                const strokeColors = ['#6474ff', '#ff8800', '#2cb96a', '#E3DC57', '#dfff00', '#00ffa6', '#000fff', 'ff008b', 'ff8a00', '#ffa500', '#7dff00', '#00fdff', '#5400ff', '#ff1300']
                const shadowColors = ['green', 'red', 'blue']
                const colroI = loc.index
                const stroke = strokeColors[colroI]
                const shadowColor = shadowColors[colroI]


                path = path + 'z'
                var fabricPath = new fabric.Path(path);
                // 对象配置
                fabricPath.set({
                  stroke,
                  strokeWidth:2,
                  fill: 'transparent',
                  lockMovementX: true,
                  lockMovementY: true,
                  hasControls: false,
                  hasBorders: false
                });
                // 点击显示的文字
                var text = new fabric.Text(loc.skuName ? loc.skuName : '未识别', {
                  ...loc,
                  fontSize: 14,
                  textBackgroundColor: 'black',
                  fill: 'white'
                  //stroke: "blue",
                })
                // 字体位置
                text.set('left', text.box_x * img.scaleX - text.box_width * img.scaleX / 2)
                text.set('top', text.box_y * img.scaleY - 20)
                var fabricPathSelected = new fabric.Path(path);
                //选中对象配置
                fabricPathSelected.set({
                  stroke,
                  strokeWidth: 4,
                  fill: 'transparent',
                  lockMovementX: true,
                  lockMovementY: true,
                  hasControls: false,
                  hasBorders: false
                });


                const tg = new fabric.Group([fabricPathSelected, text], {
                  lockMovementX: true,
                  lockMovementY: true,
                  hasControls: false,
                  hasBorders: false,
                })
                fabricPath.on('selected', () => {
                  canvas.add(tg)
                })
                fabricPath.on('deselected', () => {
                  canvas.remove(tg)
                })
                canvas.add(fabricPath)
              }
            }
            canvas.renderAll()
          },
          { crossOrigin: 'anonymous' }
        )
      })
    },
    // 绘制风幕柜不规则图形
    async drawIrregular() {
      //1.异步操作都在nextTick中返回
      this.$nextTick(() => {
        // const h = 500
        const h = 1000
        this.$refs.irregularFigureCanvasBox.style.height = h + 'px'
        //对图片进行渲染-图像文件的加载是异步的，所有对Image的后续操作都要在回调中完成
        fabric.Image.fromURL(
          this.picUrl,
          (img) => {
            let w
            img.set({ selectable: false })
            img.scaleToWidth(860)  //指定宽度
            img.scaleToHeight(1000)  //指定图片高度
            w = img.width * img.scaleX
            const canvas = new fabric.Canvas(this.$refs.canvas, {
              width: w,
              height: h,
              centeredRotation: true,
            })
            canvas.add(img)
            let results = []
            try {
              results = this.seg_algo_result || []
              // 用商品名替换掉算法名
              if (results.length > 0) {
                results.forEach((item) => {
                  this.SegBaseSkuList.forEach((skuItem) => {
                    if (item.id == skuItem.soId) {
                      item.name = item.confidence.toFixed(2) + " " + skuItem.name + " " + item.confidence.toFixed(2)
                    }
                  })

                })
              }
            } catch (error) { }
            // 1 本品 绿色框 2 竞品 红色框 3 未知 蓝色框
            const strokeColors = ['#669933', '#ff6666', '#99CCFF']
            const shadowColors = ['green', 'red', 'blue']
            const colroI = parseInt(Math.random() * 3)
            const stroke = strokeColors[colroI]
            const shadowColor = shadowColors[colroI]
            // 绘制不规则图形
            for (var i = 0; i < this.seg_algo_result.length; i++) {
              let loc = this.seg_algo_result[i]
              for (var k = 0; k < this.seg_algo_result[i].coordinate.length; k++) {
                var path = 'M'
                for (var q = 0; q < this.seg_algo_result[i].coordinate[k].length; q++) {
                  if (q === 0) {
                    path = path + " " + this.seg_algo_result[i].coordinate[k][q].x * img.scaleX + ' ' + this.seg_algo_result[i].coordinate[k][q].y * img.scaleY
                  } else {
                    path = path + ' L ' + this.seg_algo_result[i].coordinate[k][q].x * img.scaleX + ' ' + this.seg_algo_result[i].coordinate[k][q].y * img.scaleY
                  }
                }
                path = path + 'z'
                var fabricPath = new fabric.Path(path);
                // 对象配置
                fabricPath.set({
                  stroke: "green",
                  fill: 'transparent',
                  lockMovementX: true,
                  lockMovementY: true,
                  hasControls: false,
                  hasBorders: false
                });
                // 点击显示的文字
                var text = new fabric.Text(loc.name, {
                  ...loc,
                  fontSize: 14,
                  textBackgroundColor: 'black',
                  fill: 'white'
                })
                // 字体位置
                text.set('left', text.box_x * img.scaleX - text.box_width * img.scaleX / 2)
                text.set('top', text.box_y * img.scaleY - 20)
                var fabricPathSelected = new fabric.Path(path);
                // 选中对象配置
                fabricPathSelected.set({
                  stroke:'balck',
                  strokeWidth: 4,
                  fill: 'transparent',
                  lockMovementX: true,
                  lockMovementY: true,
                  hasControls: false,
                  hasBorders: false
                });
                const tg = new fabric.Group([fabricPathSelected, text], {
                  lockMovementX: true,
                  lockMovementY: true,
                  hasControls: false,
                  hasBorders: false,
                })
                fabricPath.on('selected', () => {
                  canvas.add(tg)
                })
                fabricPath.on('deselected', () => {
                  canvas.remove(tg)
                })
                canvas.add(fabricPath)
              }
            }





            // const canvas = document.querySelector('#canvas')
            // const c2 = canvas.getContext('2d')

            // // 设置属性控制图形的外观
            // c2.fillStyle = 'rgba(255, 255, 255, 0)'
            // // 外部使用外边框
            // c2.strokeStyle = '#ff0000'
            // // 线宽
            // c2.lineWidth = 2
            // c2.beginPath()
            // for (let i = 0; i <this.point_list.length; i++) {
            //     const data = this.point_list[i]
            //     if (i === 0) {
            //         c2.moveTo(data.x, data.y)
            //     }else {
            //         c2.lineTo(data.x , data.y)
            //     }
            // }
            // c2.closePath()
            // c2.fill()
            // c2.stroke()
            // canvas.add(c2)
            // for (let i = 0; i < results.length; i++) {
            //   const res = results[i]
            //   const loc=results[i]
            //   loc.top = loc.y * img.scaleY //y
            //   loc.height = loc.height * img.scaleY
            //   loc.left = loc.x * img.scaleX   //x
            //   loc.width = loc.width * img.scaleX
            //   if (!loc) continue
            //   const colroI = parseInt(Math.random() * 3)
            //   const stroke = strokeColors[colroI]
            //   const shadowColor = shadowColors[colroI]
            //   const shadow = new fabric.Shadow({ color: shadowColor, blur: 0 })
            //   const rect = new fabric.Rect({
            //     ...loc,
            //     fill: 'transparent',
            //     strokeWidth: 2,
            //     stroke,
            //     lockMovementX: true,
            //     lockMovementY: true,
            //     hasControls: false,
            //     hasBorders: false,
            //   })
            //   const text = new fabric.Text(loc.skuName, {
            //     ...loc,
            //     fontSize: 14,
            //     stroke: shadowColor,
            //   })
            //   text.set('left', text.left - text.width / 2 + loc.width / 2)
            //   text.set('top', text.top - text.height)
            //   const Trect = new fabric.Rect({
            //     top: text.top,
            //     left: text.left,
            //     width: text.width,
            //     height: text.height,
            //     fill: '#ffffff',
            //   })
            //   const tg = new fabric.Group([Trect, text], {
            //     lockMovementX: true,
            //     lockMovementY: true,
            //     hasControls: false,
            //     hasBorders: false,
            //   })
            //   rect.on('selected', () => {
            //       rect.set('stroke', shadowColor)
            //       rect.set('strokeWidth', 4)
            //       canvas.add(tg)
            //         let drawing = document.getElementById('canvasSingle')
            //         // if(drawing.getContext){
            //           const canvas2 = new fabric.Canvas(this.$refs.canvasSingle, {
            //             width: rect.width * 3,
            //             height: rect.height * 3,
            //             centeredRotation: true,
            //           })

            //           var image = new Image()
            //           image.src = this.showUrl
            //           // canvas2.add(img)
            //           let context = drawing.getContext('2d')

            //           context.drawImage(
            //             image, //要绘制的图像
            //             rect.left/(562.5/img.width), //源图像x坐标
            //             rect.top/(1000/img.height), //源图像y坐标
            //             rect.width/(562.5/img.width), //源图像宽度
            //             rect.height/(1000/img.height), //源图像高度
            //             0, //目标区域x坐标
            //             0, //目标区域y坐标
            //             rect.width * 3, //目标区域宽度
            //             rect.height * 3 //目标区域高度
            //           )

            //           let imageUrl = this.$refs.canvasSingle.toDataURL('image/jpeg')
            //           this.nowAddFile = this.base64ToFile(imageUrl,'cut'+rect.left+rect.top+'.jpg')
            //           this.nowAddUrl = imageUrl
            //           this.cutPicNum++

            //           //展示主图
            //           if(loc.url){
            //             this.nowMainPicUrl = loc.url
            //           }else{
            //             this.nowMainPicUrl = ''
            //           }
            //           if(loc.skuNameShow){
            //             this.nowMainPicName = loc.skuNameShow
            //           }else{
            //             this.nowMainPicName = ''
            //           }
            //   })
            //   rect.on('deselected', () => {
            //     // rect.shadow.blur = 0
            //     // rect.shadow.color = stroke
            //     rect.set('stroke', stroke)
            //     rect.set('strokeWidth', 2)
            //     canvas.remove(tg)
            //   })
            //   canvas.add(rect)
            // }
            canvas.renderAll()
          },
          { crossOrigin: 'anonymous' }
        )
      })
    },
    /**
     * 查看
     * @param {Object} log  当前日志信息
     */
    async showLog() {
      this.$nextTick(() => {
        // const h = 500
        const h = 1000
        this.$refs.canvasBox.style.height = h + 'px'
        //对图片进行渲染-图像文件的加载是异步的，所有对Image的后续操作都要在回调中完成
        fabric.Image.fromURL(
          this.showUrl,
          (img) => {
            let w
            img.set({ selectable: false })
            img.scaleToWidth(860)  //指定宽度
            img.scaleToHeight(1000)  //指定图片高度
            w = img.width * img.scaleX
            const canvas = new fabric.Canvas(this.$refs.canvas, {
              width: w,
              height: h,
              centeredRotation: true,
            })
            canvas.add(img)
            let results = []
            try {
              results = this.recognitionResult.results || []
              //用商品名替换掉算法名
              if (results.length > 0) {
                results.forEach((item) => {
                  this.sku_list.forEach((skuItem) => {
                    if (item.skuName == skuItem.v4SkuName) {
                      item.skuName = item.FeatureScore.toFixed(2) + " " + item.skuName + " " + item.FeatureScore.toFixed(2)
                      item.url = skuItem.imageUrl
                      //用于展示在右边主图下方，不需要识别分数
                      item.skuNameShow = skuItem.v4SkuName
                    }
                  })

                })
              }
            } catch (error) { }
            // 1 本品 绿色框 2 竞品 红色框 3 未知 蓝色框
            const strokeColors = ['#669933', '#ff6666', '#99CCFF']
            const shadowColors = ['green', 'red', 'blue']
            for (let i = 0; i < results.length; i++) {
              const res = results[i]
              // const loc = res.location
              const loc = results[i]
              // loc.TextName = 
              // if (img.width > img.height) {
              //   let t = loc.top
              //   loc.top = loc.left
              //   loc.left = t
              //   t = loc.width
              //   loc.width = loc.height
              //   loc.height = t
              // }
              loc.top = loc.y * img.scaleY //y
              loc.height = loc.height * img.scaleY
              loc.left = loc.x * img.scaleX   //x
              loc.width = loc.width * img.scaleX
              if (!loc) continue
              const colroI = parseInt(Math.random() * 3)
              const stroke = strokeColors[colroI]
              const shadowColor = shadowColors[colroI]
              const shadow = new fabric.Shadow({ color: shadowColor, blur: 0 })
              const rect = new fabric.Rect({
                ...loc,
                fill: 'transparent',
                strokeWidth: 2,
                stroke,
                lockMovementX: true,
                lockMovementY: true,
                hasControls: false,
                hasBorders: false,
              })
              const text = new fabric.Text(loc.skuName, {
                ...loc,
                fontSize: 14,
                stroke: shadowColor,
              })
              text.set('left', text.left - text.width / 2 + loc.width / 2)
              text.set('top', text.top - text.height)
              const Trect = new fabric.Rect({
                top: text.top,
                left: text.left,
                width: text.width,
                height: text.height,
                fill: '#ffffff',
              })
              const tg = new fabric.Group([Trect, text], {
                lockMovementX: true,
                lockMovementY: true,
                hasControls: false,
                hasBorders: false,
              })
              rect.on('selected', () => {
                rect.set('stroke', shadowColor)
                rect.set('strokeWidth', 4)
                canvas.add(tg)
                let drawing = document.getElementById('canvasSingle')
                var image = new Image()
                image.src = this.showUrl
                let context = drawing.getContext('2d')
                context.drawImage(
                  image, //要绘制的图像
                  rect.left / (562.5 / img.width), //源图像x坐标
                  rect.top / (1000 / img.height), //源图像y坐标
                  rect.width / (562.5 / img.width), //源图像宽度
                  rect.height / (1000 / img.height), //源图像高度
                  0, //目标区域x坐标
                  0, //目标区域y坐标
                  rect.width * 3, //目标区域宽度
                  rect.height * 3 //目标区域高度
                )

                let imageUrl = this.$refs.canvasSingle.toDataURL('image/jpeg')
                this.nowAddFile = this.base64ToFile(imageUrl, 'cut' + rect.left + rect.top + '.jpg')
                this.nowAddUrl = imageUrl
                this.cutPicNum++

                //展示主图
                if (loc.url) {
                  this.nowMainPicUrl = loc.url
                } else {
                  this.nowMainPicUrl = ''
                }
                if (loc.skuNameShow) {
                  this.nowMainPicName = loc.skuNameShow
                } else {
                  this.nowMainPicName = ''
                }
              })
              rect.on('deselected', () => {
                // rect.shadow.blur = 0
                // rect.shadow.color = stroke
                rect.set('stroke', stroke)
                rect.set('strokeWidth', 2)
                canvas.remove(tg)
              })
              canvas.add(rect)
            }
            canvas.renderAll()
          },
          { crossOrigin: 'anonymous' }
        )
      })
    },
    handIrregularFigureFileChange(e) {
      let fileData = e.target.files[0]
      // 限制上传的图片类型
      if (fileData.type == 'image/jpeg' || fileData.type == 'image/png') {
        this.irregularFigureForm.packageFile = fileData
        let url = URL.createObjectURL(fileData)
        this.picUrl = url
      } else {
        this.$message.warning("当前仅支持jpg和png格式的图片")
        return
      }
    },
    //v5算法图片上传
    v5FileChange(e) {
      let fileData = e.target.files[0]
      // 限制上传的图片类型
      if (fileData.type == 'image/jpeg' || fileData.type == 'image/png') {
        this.v5Form.packageFile = fileData
        let url = URL.createObjectURL(fileData)
        this.picUrl = url
      } else {
        this.$message.warning("当前仅支持jpg和png格式的图片")
        return
      }
    },
    /** 异常测试-图片文件上传 */
    handErrorTestFileChange(e){
      let fileData = e.target.files[0]
      // 限制上传的图片类型
      if (fileData.type == 'image/jpeg' || fileData.type == 'image/png') {
        this.errorTestForm.packageFile = fileData
        let url = URL.createObjectURL(fileData)
        this.picUrl = url
      } else {
        this.$message.warning("当前仅支持jpg和png格式的图片")
        return
      }
    },
    /** 算法识别-图片文件上传 */
    handFileChange(e) {
      let fileData = e.target.files[0]
      // 限制上传的图片类型
      if (fileData.type == 'image/jpeg' || fileData.type == 'image/png') {
        this.recognitionForm.packageFile = fileData
        let url = URL.createObjectURL(fileData)
        this.picUrl = url
      } else {
        this.$message.warning("当前仅支持jpg和png格式的图片")
        return
      }
    },
    /** 获取项目列表 */
    getProjectList() {
      const params = {
        pageNum: 1,
        pageSize: 100,
      }
      listProject(params).then((res) => {
        if (res.code === 200 && res.rows.length > 0) {
          this.project_list = res.rows.map((item) => {
            return {
              name: item.projectName,
              id: item.id
            }
          })
        }
      }).catch((err) => {
        this.$message.error("项目获取失败!", err.message)
      })
    },
    /** 算法识别-弹框取消 */
    cancel() {
      this.errorThresholdSetdialogOpen = false;
      this.errorTestdialogOpen = false;
      this.editRecResultDialogOpen = false;
      this.irregularFigureDialogOpen = false;
      this.dialogOpen = false;
      this.shelterDialogOpen = false;
      this.shelterValueSettingDialogOpen = false;
      this.v5DialogOpen = false;
      this.v5Form.packageFile = null
      this.v5ResultDialogOpen = false;
      this.irregularFigureResultDialogOpen = false
      // this.$refs.packageFile.value=''
      if (this.$refs.segPackageFile) {
        this.$refs.segPackageFile.value = ''
      }
      if (this.$refs.v5PackageFile) {
        this.$refs.v5PackageFile.value = ''
      }
      this.picUrl = ''
    },
    /** 点击绘制不规则图形按钮 */
    irregularFigure() {
      this.loading = true
      this.getProjectList();
      this.irregularFigureDialogOpen = true;
      this.irregularFigureForm.projectId = null;
      this.irregularFigureForm.direction = '';
      this.irregularFigureForm.containerType = '';
      this.irregularFigureForm.urlPath = '';
      this.irregularFigureForm.packageFile = '';
    },
    // 获取要修改的图片和结果的列表
    getResultList(){
      listProject(params).then((res) => {
        if (res.code === 200 && res.rows.length > 0) {
          // this.result_list = res.rows.map((item) => {
          //   return {
          //     name: item.projectName,
          //     id: item.id
          //   }
          // })
        }
      }).catch((err) => {
        this.$message.error("算法结果列表获取失败!", err.message)
      })
    },
    handleV5() {
      this.getProjectList();
      this.v5DialogOpen = true;
      this.v5Form.projectId = null;
      this.v5Form.containerType = 1;
      this.v5Form.urlPath = '';
      this.v5Form.packageFile = '';
      this.v5Form.model = null;
    },
    /** 搜索按钮操作 */
    handleQuery(type) {
      // 当项目列表为空时，获取
      if (this.project_list.length === 0) {
        this.getProjectList()
      }
      this.recognitionForm.projectId = ''
      this.recognitionForm.imageUrl = ''
      this.picUrl = ''
      this.recognitionForm.packageFile = ''
      this.dialogOpen = true
      this.resultType = type
    },
    /** 图片油污检测按钮-点击 */
    handleOilStain() {
      this.oilStainDialogOpen = true
      this.oilStainJudgeForm.imageUrl = ''
      this.oilStainJudgeForm.packageFile = ''
      this.oilStainJudgeForm.picUrl = ''
    },
    /** 油污阈值设置 */
    handleOilStainValueSetting() {
      this.oilStainValueSettingDialogOpen = true
      this.oilStainValueSettingForm = {
        userId: '',  //用户id
        twoUserId: '',
        threeUserId: '',
        fourUserId: '',
        fiveUserId: '',
        sixUserId: '',
        enable: '', //是否启用算法识别 true false
        sieveEnable: '', // 是否启用有无检测 true false
        sieveThreshold: '' //  油污阈值
      }
    },
    /** 遮挡阈值设置 */
    handleShelterValueSetting() {
      this.shelterValueSettingDialogOpen = true
      this.shelterValueSettingForm = {
        threshold: '',
      }
    }

  }
}
  ;
</script>
<style lang="scss">
.el-message-box {
  display: inline-block;
  width: 820px;
  padding-bottom: 10px;
  vertical-align: middle;
  background-color: #FFFFFF;
  border-radius: 4px;
  border: 1px solid #e6ebf5;
  font-size: 18px;
  -webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  text-align: left;
  overflow: hidden;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
</style>
